﻿Public Class frmPayroll
    Dim validator As PropertyValidator = New PropertyValidator
    Dim payrollManager As New PayrollManager
    Dim holidayManager As New HolidayManager
    Dim employeeInfoManager As New EmployeeInfoManager
    Dim leaveManager As New LeaveManager
    Dim otManager As New OvertimeManager

    Dim EmpData As Employee
    Sub New(ByVal emp As Employee)

        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        EmpData = emp
    End Sub

    Private Sub frmPayroll_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        ClearAllFields()
        PopulateEmployeeName(cboEmployeeName)
    End Sub

    Public Function ClearAllFields()
        validator.ResetControls(grpPayroll)
        btnSave.Text = "&Save"
        btnCancel.Text = "&Clear"
        btnCompute.Text = "&Compute"
        txtTaxableIncome.Text = ""
        txtNetPay.Text = ""
        Return 0
    End Function
    Public Function PopulateEmployeeName(ByVal cbo As ComboBox)

        Dim dataTable As New DataTable
        dataTable.Columns.Add("id")
        dataTable.Columns.Add("employeeName")
        Dim employeeList As List(Of EmployeeInfo) = employeeInfoManager.getAllEmployeesInfo()
        For Each employee As EmployeeInfo In employeeList
            dataTable.Rows.Add(employee.employee_id, employee.last_name & "," & employee.first_name)
        Next

        cbo.DataSource = dataTable
        cbo.DisplayMember = "employeeName"
        cbo.ValueMember = "id"
        cbo.SelectedIndex = -1

        Return (0)
    End Function


   
    Private Sub btnCompute_Click(sender As System.Object, e As System.EventArgs) Handles btnCompute.Click
        If (Convert.ToInt16(cboEmployeeName.SelectedIndex > -1)) Then

            'Get Employee Information
            Dim emp As Employee = New EmployeeManager().retrieveEmployeeById(Convert.ToInt64(cboEmployeeName.SelectedValue.ToString()))
            Dim empInfo As EmployeeInfo = New EmployeeInfoManager().retrieveEmployeeInfoByEmployeeId(emp.id)

            'Fill in salary
            txtSalary.Text = emp.salary
            Dim salary As Double = 0D
            Double.TryParse(txtSalary.Text, salary)

            Dim missingTimeIn As New List(Of String)
            Dim missingTimeOut As New List(Of String)

            'Benefits Computation
            Dim totalBenefitsDeduction As Double = 0D
            totalBenefitsDeduction = manageBenefits(emp)


            'get Basic Pay*******************************************************
            Dim basicPay As Double = 0D
            basicPay = (salary * 12) / 313
            basicPay = Math.Round(basicPay, 2, MidpointRounding.AwayFromZero)
            txtBasicPay.Text = basicPay.ToString
            '********************************************************************

            'get OT Pay*******************************************************
            Dim otPay As Double = 0D
            Dim otHours As Integer = 0D
            Dim otFrom As DateTime = DateTime.Parse(dtpFrom.Value.ToString("yyyy-MM-dd") + " 00:00:00")
            Dim otTo As DateTime = DateTime.Parse(dtpTo.Value.ToString("yyyy-MM-dd") + " 23:59:59")

            otHours = otManager.computeTotalOvertimeHours(otFrom, otTo, emp)
            otPay = ((basicPay / 8) * 1.25D) * otHours
            otPay = Math.Round(otPay, 2, MidpointRounding.AwayFromZero)
            txtOTHours.Text = otHours.ToString
            txtOTPay.Text = otPay.ToString
            '********************************************************************

            'attendance related**************************************************
            Dim startDate As String = dtpFrom.Value.ToString("yyyy-MM-dd")
            Dim endDate As String = dtpTo.Value.ToString("yyyy-MM-dd")



            Dim loopDate As DateTime = DateTime.Parse(startDate)


            Dim totalHours As Double = 0D
            Dim totalLateMinutes As Double = 0D
            Dim totalSpecialHolidayHours As Double = 0D
            Dim totalLegalHolidayHours As Double = 0D
            Dim totalNightDiffHours As Double = 0D
            Dim hoursPerDay As Double = 0D

            While loopDate <= DateTime.Parse(endDate)
                'if this day the employee is on leave automatically +8 to total hours worked
                If Not leaveManager.isApprovedLeave(loopDate.ToString("yyyy-MM-dd"), emp) Then
                    Dim logs As New List(Of LogBiometrics)
                    Dim temp As List(Of LogBiometrics) = New LogBiometricsManager().retrieveLogBioByDate(emp.id, (loopDate.ToString("yyyy-MM-dd") + " 00:00:00"), (loopDate.ToString("yyyy-MM-dd") + " 23:59:59"))
                    Dim ndiffStart As DateTime = DateTime.Parse(loopDate.ToString("yyyy-MM-dd") + " 22:00:00")
                    Dim ndiffEnd As DateTime = DateTime.Parse(loopDate.ToString("yyyy-MM-dd") + " 06:00:00")


                    If Not temp Is Nothing Then
                        logs = temp
                        If logs.Count > 0 Then



                            If emp.flexitime.Equals("1") Then 'flexitime
                                hoursPerDay = 12
                                Dim startTime As DateTime = loopDate.ToString("yyyy-MM-dd") + " 00:00:00"
                                Dim countStart As Boolean = True
                                If logs.Count > 0 Then
                                    If logs(0).log_type = 0 Then countStart = False
                                End If
                                For Each log As LogBiometrics In logs
                                    'if 0 = Login, 1=Logout
                                    If log.log_type = 0 Then
                                        If Not countStart Then
                                            countStart = True
                                            startTime = DateTime.Parse(log.time_log)
                                        End If
                                    ElseIf countStart Then
                                        countStart = False
                                        Dim endTime As DateTime = DateTime.Parse(log.time_log)
                                        Dim elapsedTime As TimeSpan = endTime.Subtract(startTime)
                                        totalHours += elapsedTime.TotalHours

                                        'night diff
                                        Dim elapsedTime2 As TimeSpan
                                        If startTime < ndiffEnd Then
                                            If endTime <= ndiffEnd Then
                                                elapsedTime2 = endTime.Subtract(startTime)
                                            ElseIf endTime >= ndiffEnd And endTime <= ndiffStart Then
                                                elapsedTime2 = ndiffEnd.Subtract(startTime)
                                            ElseIf endTime >= ndiffStart Then
                                                elapsedTime2 = ndiffStart.Subtract(startTime)
                                            End If
                                        ElseIf startTime >= ndiffEnd Then
                                            If endTime > ndiffStart Then
                                                elapsedTime2 = endTime.Subtract(ndiffStart)
                                            End If
                                        ElseIf startTime >= ndiffStart Then
                                            elapsedTime2 = endTime.Subtract(startTime)
                                        End If
                                        totalNightDiffHours += elapsedTime2.TotalHours

                                        'special holiday
                                        If holidayManager.isSpecialHoliday(loopDate) Then totalSpecialHolidayHours += elapsedTime.TotalHours
                                        'legal holiday
                                        If holidayManager.isLegalHoliday(loopDate) Then totalLegalHolidayHours += elapsedTime.TotalHours
                                    End If
                                Next

                                'if no time out since last time-in in this loopdate
                                'the system will count the 23:59:59 as time out to compute for the hours worked
                                If logs.Count > 0 And countStart Then
                                    countStart = False
                                    Dim endTime As DateTime = DateTime.Parse(loopDate.ToString("yyyy-MM-dd") + " 23:59:59")
                                    Dim elapsedTime As TimeSpan = endTime.Subtract(startTime)
                                    totalHours += elapsedTime.TotalHours

                                    'special holiday
                                    If holidayManager.isSpecialHoliday(loopDate) Then totalSpecialHolidayHours += elapsedTime.TotalHours

                                    'legal holiday
                                    If holidayManager.isLegalHoliday(loopDate) Then totalLegalHolidayHours += elapsedTime.TotalHours

                                    'night diff
                                    Dim elapsedTime2 As TimeSpan
                                    If startTime < ndiffEnd Then
                                        If endTime <= ndiffEnd Then
                                            elapsedTime2 = endTime.Subtract(startTime)
                                        ElseIf endTime >= ndiffEnd And endTime <= ndiffStart Then
                                            elapsedTime2 = ndiffEnd.Subtract(startTime)
                                        ElseIf endTime >= ndiffStart Then
                                            elapsedTime2 = ndiffStart.Subtract(startTime)
                                        End If
                                    ElseIf startTime >= ndiffEnd Then
                                        If endTime > ndiffStart Then
                                            elapsedTime2 = endTime.Subtract(ndiffStart)
                                        End If
                                    ElseIf startTime >= ndiffStart Then
                                        elapsedTime2 = endTime.Subtract(startTime)
                                    End If
                                    totalNightDiffHours += elapsedTime2.TotalHours
                                End If
                            Else 'regular shift**********************************************
                                hoursPerDay = 8
                                'get the earliest time in
                                Dim earliest As DateTime
                                Dim latest As DateTime

                                For Each log As LogBiometrics In logs
                                    If log.log_type = 0 Then
                                        earliest = DateTime.Parse(log.time_log)
                                        Exit For

                                    End If
                                Next

                                If Not earliest = Nothing Then
                                    'check if late
                                    Dim lateCheck As DateTime = DateTime.Parse(loopDate.ToString("yyyy-MM-dd") + " " + emp.time_in)
                                    If earliest > lateCheck Then
                                        'late
                                        Dim lateMinutes As TimeSpan = earliest.Subtract(lateCheck)
                                        totalLateMinutes += lateMinutes.TotalMinutes
                                    End If
                                Else
                                    missingTimeIn.Add(loopDate.ToString("MM-dd-yyyy"))
                                End If

                                'get the latest time out

                                For i = logs.Count - 1 To 0 Step -1
                                    If logs(i).log_type = 1 Then
                                        latest = DateTime.Parse(logs(i).time_log)
                                        Exit For
                                    End If
                                Next
                                If latest = Nothing Then
                                    missingTimeOut.Add(loopDate.ToString("MM-dd-yyyy"))
                                End If
                                If Not earliest = Nothing And Not latest = Nothing Then
                                    Dim elapsedTime As TimeSpan = latest.Subtract(earliest)
                                    Dim hours As Double = 0D
                                    If elapsedTime.TotalHours >= hoursPerDay Then
                                        totalHours += hoursPerDay
                                        hours = hoursPerDay
                                    ElseIf elapsedTime.TotalHours < 0 Then
                                        missingTimeOut.Add(loopDate.ToString("MM-dd-yyyy"))
                                    Else
                                        'TODO -1 for lunch break
                                        totalHours += Math.Round(elapsedTime.TotalHours, 2, MidpointRounding.AwayFromZero) - 1
                                        hours = Math.Round(elapsedTime.TotalHours, 2, MidpointRounding.AwayFromZero)
                                    End If


                                    'special holiday
                                    If holidayManager.isSpecialHoliday(loopDate) Then totalSpecialHolidayHours += If((hours >= hoursPerDay), hoursPerDay, hours)
                                    'legal holiday
                                    If holidayManager.isLegalHoliday(loopDate) Then totalLegalHolidayHours += If((hours >= hoursPerDay), hoursPerDay, hours)


                                    'night diff
                                    Dim elapsedTime2 As TimeSpan
                                    If earliest < ndiffEnd Then
                                        If latest <= ndiffEnd Then
                                            elapsedTime2 = latest.Subtract(earliest)
                                        ElseIf latest >= ndiffEnd And latest <= ndiffStart Then
                                            elapsedTime2 = ndiffEnd.Subtract(earliest)
                                        ElseIf latest >= ndiffStart Then
                                            elapsedTime2 = ndiffStart.Subtract(earliest)
                                        End If
                                    ElseIf earliest >= ndiffEnd Then
                                        If latest > ndiffStart Then
                                            elapsedTime2 = latest.Subtract(ndiffStart)
                                        End If
                                    ElseIf earliest >= ndiffStart Then
                                        elapsedTime2 = latest.Subtract(earliest)
                                    End If
                                    totalNightDiffHours += elapsedTime2.TotalHours
                                End If



                            End If 'end regular shift**********************************************
                        Else
                            'special holiday
                            If holidayManager.isSpecialHoliday(loopDate) Then totalSpecialHolidayHours += hoursPerDay
                            'legal holiday
                            If holidayManager.isLegalHoliday(loopDate) Then totalLegalHolidayHours += hoursPerDay
                        End If



                    End If '**********************************************************
                Else
                    'employee is on leave so add 8 hours

                    If emp.flexitime.Equals("1") Then
                        hoursPerDay = 12
                    Else
                        hoursPerDay = 8
                    End If
                    totalHours += hoursPerDay
                End If
                loopDate = loopDate.AddDays(1)
            End While

            'populate the fields 
            txtWorkedHours.Text = "" + Math.Round(totalHours, 2, MidpointRounding.AwayFromZero).ToString

            Dim lateDeduction As Double = 0D
            If totalLateMinutes > 0 Then

                lateDeduction = (basicPay / hoursPerDay) * (totalLateMinutes / 60)
                txtDeduction1Name.Text = "Late (" + Math.Round((totalLateMinutes / 60), 2, MidpointRounding.AwayFromZero).ToString.ToString + ")"
                txtDeduction1Amount.Text = "" + lateDeduction.ToString
            End If

            Dim nDiffPay As Double = 0D
            If totalNightDiffHours > 0 Then

                nDiffPay = Math.Truncate(((basicPay / hoursPerDay) * 0.1) * totalNightDiffHours)
                txtNightDiffHours.Text = totalNightDiffHours
                txtNightDiffPay.Text = nDiffPay.ToString
            End If

            Dim sholidayPay As Double = 0D
            If totalSpecialHolidayHours > 0 Then

                sholidayPay = Math.Truncate(((basicPay / hoursPerDay) * 0.3) * totalSpecialHolidayHours)
                txtIncentive1Name.Text = "S. Holiday (" + totalSpecialHolidayHours.ToString + ")"
                txtIncentive1Amount.Text = sholidayPay.ToString
            End If

            Dim lholidayPay As Double = 0D
            If totalLegalHolidayHours > 0 Then

                lholidayPay = Math.Truncate(((basicPay / hoursPerDay) * 1) * totalLegalHolidayHours)
                txtIncentive2Name.Text = "L. Holiday (" + totalLegalHolidayHours.ToString + ")"
                txtIncentive2Amount.Text = lholidayPay.ToString
            End If

            Dim i1Amount As Double = 0D
            Dim i2Amount As Double = 0D
            Dim i3Amount As Double = 0D
            Double.TryParse(txtIncentive1Amount.Text, i1Amount)
            Double.TryParse(txtIncentive2Amount.Text, i2Amount)
            Double.TryParse(txtIncentive3Amount.Text, i3Amount)

            Dim grossIncome As Double = 0D
            grossIncome = ((basicPay / hoursPerDay) * Math.Round((totalHours), 2, MidpointRounding.AwayFromZero)) + nDiffPay + i1Amount + i2Amount + i3Amount
            txtGrossIncome.Text = Math.Round((grossIncome), 2, MidpointRounding.AwayFromZero).ToString



            Dim d1Amount As Double = 0D
            Dim d2Amount As Double = 0D
            Dim d3Amount As Double = 0D
            Double.TryParse(txtDeduction1Amount.Text, d1Amount)
            Double.TryParse(txtDeduction2Amount.Text, d2Amount)
            Double.TryParse(txtDeduction3Amount.Text, d3Amount)

            Dim tIncome As Double = 0D
            tIncome = grossIncome - totalBenefitsDeduction - d1Amount - d2Amount - d3Amount
            txtTaxableIncome.Text = tIncome.ToString

            Dim tDeduction As Double = 0D
            tDeduction = tIncome * 0.12
            txtTaxDeduction.Text = Math.Round((tDeduction), 2, MidpointRounding.AwayFromZero).ToString

            Dim netPay As Double = 0D
            netPay = tIncome - (tIncome * 0.12)
            txtNetPay.Text = Math.Round((netPay), 2, MidpointRounding.AwayFromZero).ToString

            'prompt for missing time ins and time outs
            If missingTimeIn.Count > 0 Or missingTimeOut.Count > 0 Then
                Dim missingMsg As String = "Employee "
                missingMsg += If((empInfo.first_name.Length <= 0 And empInfo.last_name.Length <= 0 And empInfo.employee_no >= 0), " no. " + empInfo.employee_no, "")
                missingMsg += If((empInfo.first_name.Length > 0), empInfo.first_name, "")
                missingMsg += If((empInfo.last_name.Length > 0), " " + empInfo.last_name, "")
                missingMsg += If((missingTimeIn.Count > 0), " missing Time In Dates :" + String.Join(",", missingTimeIn), "")
                missingMsg += If((missingTimeOut.Count > 0), " missing Time Out Dates :" + String.Join(",", missingTimeOut), "")
                MsgBox(missingMsg)
            End If
        End If

    End Sub

    Private Function manageBenefits(ByVal emp As Employee) As Double
        Dim totalDeduction As Double = 0D

        'Get All SSS
        Dim sssList As List(Of SSS) = payrollManager.getAllSSS()
        'Loop and identify the sss contribution of employee
        For Each sss As SSS In sssList
            If emp.salary >= sss.min_salary Then
                If emp.salary <= sss.max_salary Then
                    txtSSSAmount.Text = sss.employee_share.ToString()
                End If
            Else
                Continue For
            End If
        Next
        'if sss contribution is still 0.00 check if salary exceeds max salary
        If txtSSSAmount.Text.Equals("0.00") Then
            Dim lastRow As SSS = sssList(sssList.Count - 1)
            If emp.salary >= lastRow.min_salary Then
                If emp.salary >= lastRow.max_salary Then
                    txtSSSAmount.Text = lastRow.employee_share.ToString
                End If
            End If
        End If

        'Get all Pagibig List
        Dim pagibigList As List(Of PagIBIG) = payrollManager.getAllPagIBIG()
        'Loop and identify the pagibig contribution of employee
        For Each pagibig As PagIBIG In pagibigList
            If pagibig.min_salary <= emp.salary And emp.salary <= pagibig.max_salary Then
                txtPagIBIGAmount.Text = pagibig.employee_share.ToString()
            End If
        Next
        'if pagibig contribution is still 0.00 check if salary exceeds max salary
        If txtPagIBIGAmount.Text.Equals("0.00") Then
            Dim lastRow As PagIBIG = pagibigList(pagibigList.Count - 1)
            If emp.salary >= lastRow.min_salary Then
                If emp.salary >= lastRow.max_salary Then
                    txtPagIBIGAmount.Text = lastRow.employee_share.ToString
                End If
            End If
        End If

        'get all philhealth list
        Dim phiList As List(Of PhilHealth) = payrollManager.getAllPHI()
        'Loop and identify the pagibig contribution of employee
        For Each philhealth As PhilHealth In phiList
            If philhealth.min_salary <= emp.salary And emp.salary <= philhealth.max_salary Then
                txtPhilHealthAmount.Text = philhealth.employee_share.ToString()
            End If
        Next
        'if philhealth contribution is still 0.00 check if salary exceeds max salary
        If txtPhilHealthAmount.Text.Equals("0.00") Then
            Dim lastRow As PhilHealth = phiList(phiList.Count - 1)
            If emp.salary >= lastRow.min_salary Then
                If emp.salary >= lastRow.max_salary Then
                    txtPhilHealthAmount.Text = lastRow.employee_share.ToString
                End If
            End If
        End If

        Dim sssAmount As Double = 0D
        Dim philhealthAmount As Double = 0D
        Dim pagibiAgmount As Double = 0D
        Double.TryParse(txtSSSAmount.Text, sssAmount)
        Double.TryParse(txtPhilHealthAmount.Text, philhealthAmount)
        Double.TryParse(txtPagIBIGAmount.Text, pagibiAgmount)

        totalDeduction = sssAmount + philhealthAmount + pagibiAgmount

        Return totalDeduction
    End Function

  

    Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click
        If validator.IsNumericString(txtSalary, "Salary") Then Return
        If validator.IsNumericString(txtWorkedHours, "Worked Hours") Then Return
        If validator.IsNumericString(txtBasicPay, "Basic Pay") Then Return
        If validator.IsNumericString(txtOTHours, "Overtime Hours") Then Return
        If validator.IsNumericString(txtOTPay, "Overtime Pay") Then Return



        'If Not validator.IsNumericString(txtIncentive1Amount, "Incentive 1") Then
        '    txtIncentive1Amount.Text = "0.00"
        'End If
        'If Not validator.IsNumericString(txtIncentive2Amount, "Incentive 2") Then
        '    txtIncentive2Amount.Text = "0.00"
        'End If
        'If Not validator.IsNumericString(txtIncentive3Amount, "Incentive 3") Then
        '    txtIncentive3Amount.Text = "0.00"
        'End If

        'If Not validator.IsNumericString(txtDeduction1Amount, "Deduction 1") Then
        '    txtDeduction1Amount.Text = "0.00"
        'End If
        'If Not validator.IsNumericString(txtDeduction2Amount, "Deduction 2") Then
        '    txtDeduction2Amount.Text = "0.00"
        'End If
        'If Not validator.IsNumericString(txtDeduction3Amount, "Deduction 3") Then
        '    txtDeduction3Amount.Text = "0.00"
        'End If


        If validator.IsNumericString(txtSSSAmount, "SSS Amount") Then Return
        If validator.IsNumericString(txtPhilHealthAmount, "PhilHealth Amount") Then Return
        If validator.IsNumericString(txtPagIBIGAmount, "Pag-IBIG Amount") Then Return
        If validator.IsNumericString(txtTaxableIncome, "Taxable Income") Then Return
        If validator.IsNumericString(txtNetPay, "Net Pay") Then Return

        'Get Employee Information
        Dim emp As Employee = New EmployeeManager().retrieveEmployeeById(Convert.ToInt64(cboEmployeeName.SelectedValue.ToString()))
        
        Dim payrollObj As New Payroll
        payrollObj.employee_id = emp.id
        payrollObj.date_from = dtpFrom.Value.ToString("yyyy-M-d")
        payrollObj.date_to = dtpTo.Value.ToString("yyyy-M-d")
        payrollObj.salary = FormatNumber(CDbl(txtSalary.Text), 2)
        payrollObj.worked_hours = txtWorkedHours.Text
        payrollObj.basic_pay = FormatNumber(CDbl(txtBasicPay.Text), 2)
        payrollObj.ot_hours = txtOTHours.Text
        payrollObj.ot_pay = FormatNumber(CDbl(txtOTPay.Text), 2)


        payrollObj.incentive_1_name = txtIncentive1Name.Text
        payrollObj.incentive_1_amount = FormatNumber(CDbl(txtIncentive1Amount.Text), 2)
        payrollObj.incentive_2_name = txtIncentive2Name.Text
        payrollObj.incentive_2_amount = FormatNumber(CDbl(txtIncentive2Amount.Text), 2)
        payrollObj.incentive_3_name = txtIncentive3Name.Text
        payrollObj.incentive_3_amount = FormatNumber(CDbl(txtIncentive3Amount.Text), 2)

        payrollObj.sss_amount = FormatNumber(CDbl(txtSSSAmount.Text), 2)
        payrollObj.philhealth_amount = FormatNumber(CDbl(txtPhilHealthAmount.Text), 2)
        payrollObj.pagibig_amount = FormatNumber(CDbl(txtPagIBIGAmount.Text), 2)

        payrollObj.deduction_1_name = txtDeduction1Name.Text
        payrollObj.deduction_1_amount = FormatNumber(CDbl(txtDeduction1Amount.Text), 2)
        payrollObj.deduction_2_name = txtDeduction2Name.Text
        payrollObj.deduction_2_amount = FormatNumber(CDbl(txtDeduction2Amount.Text), 2)
        payrollObj.deduction_3_name = txtDeduction3Name.Text
        payrollObj.deduction_3_amount = FormatNumber(CDbl(txtDeduction3Amount.Text), 2)

        payrollObj.taxable_income = FormatNumber(CDbl(txtTaxableIncome.Text), 2)
        payrollObj.net_pay = FormatNumber(CDbl(txtNetPay.Text), 2)

        payrollManager.insertPayroll(payrollObj)
        MsgBox("Successfully Saved")

    End Sub

    Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
        ClearAllFields()
    End Sub


End Class